package com.take.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "token.jwt")
public class JwtTokenUtils {
    private String secret;
    private long expire;
    private String header;

    //生成token
    public String generateJwt(Map<String, Object> claims) {
        Date nowDate = new Date();
        //过期时间
        Date expireDate = new Date(nowDate.getTime() + expire * 1000);

        return Jwts.builder()
                .setClaims(claims) //自定义内容
                .signWith(SignatureAlgorithm.HS256, secret)//签名算法
                .setExpiration(new Date(System.currentTimeMillis() + 12 * 3600)) //有效期
                .setIssuedAt(nowDate)    //token签发时间
                .setExpiration(expireDate)
                .compact();
    }

    //解析token
    public Claims parseJwt(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }


    /**
     * 签发令牌(用userId生成jwt token)
     * jwt字符串包括三个部分
     * 1. header
     * -当前字符串的类型typ，一般都是“JWT”
     * -哪种算法加密，“HS256”或者其他的加密算法
     * 2. payload
     * 一般有四个最常见的标准字段（下面有）
     * iat：签发时间，也就是这个jwt什么时候生成的
     * jti：JWT的唯一标识
     * iss：签发人，一般都是username或者userId
     * exp：过期时间
     * <p>
     * claims 中存储的一些非隐私信息
     * shiroSessionId 是JWT的唯一标识，用于将jwt token 缓存到session中
     */
    public String generateCodeToken(String code) {
        Date nowDate = new Date();
        //过期时间
        Date expireDate = new Date(nowDate.getTime() + expire * 1000);

        String token = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setId(code)   //JWT的唯一标识，一般设置成唯一的，存储为sessionId,以便登录成功后回写
                //.setId(UUID.randomUUID().toString())
                .setSubject("VERIFY_CODE")
                .setIssuedAt(nowDate)    //token签发时间
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();

        return token;
    }

    // 获取jwt的信息
    public Claims getClaimByToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            return claims;
        } catch (Exception e) {
            log.debug("validate is token error ", e);

        }
        return null;
    }

    /**
     * token是否过期
     *
     * @return true：过期
     */
    public boolean isTokenExpired(Date expiration) {
        return expiration.before(new Date());
    }
}
